home *** CD-ROM | disk | FTP | other *** search
/ MacWorld 1998 March / Macworld (1998-03) (Disk 1).dmg / Shareware World / Utilities / Text Processing / Alpha / Tcl / SystemCode / templates.tcl < prev    next >
Encoding:
Text File  |  1997-12-17  |  7.3 KB  |  254 lines  |  [TEXT/ALFA]

  1. ## -*-Tcl-*-
  2.  # ###################################################################
  3.  #  Vince's Additions - an extension package for Alpha
  4.  # 
  5.  #  FILE: "templates.tcl"
  6.  #                                    created: 27/7/97 {9:29:20 pm} 
  7.  #                                last update: 17/12/97 {4:25:19 pm} 
  8.  #  Author: Vince Darley
  9.  #  E-mail: <darley@fas.harvard.edu>
  10.  #    mail: Division of Engineering and Applied Sciences, Harvard University
  11.  #          Oxford Street, Cambridge MA 02138, USA
  12.  #     www: <http://www.fas.harvard.edu/~darley/>
  13.  #  
  14.  # Copyright (c) 1997  Vince Darley
  15.  # 
  16.  # Simple template insertion mechanism.  Can be easily overridden
  17.  # by a more sophisticated scheme providing more features, whilst
  18.  # still working simply if desired.  Call any of these 
  19.  # procs from the outside:
  20.  # 
  21.  #  elec::Insertion args  -- insert the given args
  22.  #  elec::CenterInsertion args -- insert, then center redraw
  23.  #  elec::Wrap left right -- wrap left and right about the selection
  24.  #  
  25.  #  ring::+ -- move to the next template stop
  26.  #  ring::- -- move to the previous template stop
  27.  #  
  28.  # Any piece of text given to the three 'elec::' procs has a template
  29.  # conversion done.  Text of the form '•blah•' is converted to a single
  30.  # bullet '•', with 'blah' attached to it internally.  
  31.  # 
  32.  # A more sophisticated template package, available separately, can
  33.  # prompt the user with 'blah' in useful ways, and creates a proper
  34.  # template ring.
  35.  # 
  36.  #  modified by  rev reason
  37.  #  -------- --- --- -----------
  38.  #  27/7/97  VMD 1.0 original
  39.  # ###################################################################
  40.  ##
  41.  
  42. namespace eval elec {}
  43. namespace eval bind {}
  44. namespace eval ring {}
  45.  
  46. proc alpha::useElectricTemplates {} {}
  47.  
  48. ## 
  49.  # -------------------------------------------------------------------------
  50.  #     
  51.  #    "elec::_Insertion" --
  52.  #    
  53.  #     Insert    a piece    of text, padding on    the    left appropriately.     The text 
  54.  #     should    already    be correctly indented within itself.  
  55.  #     
  56.  #     Any piece of the text of the form '•blah•' is converted into a single
  57.  #     bullet.  A more advanced version of this procedure, available
  58.  #     separately, allows the use of '•blah•' to prompt the user either
  59.  #     in the window, or status line, and makes the template stops permanent
  60.  #     entities so you can cycle back and forth through a template 'ring'.
  61.  # -------------------------------------------------------------------------
  62.  ##
  63. proc elec::_Insertion { center args } {
  64.     set text [join $args ""]
  65.     set pos [getPos]
  66.     regsub -all "\t" $text [text::Tab] text
  67.     if [regexp "\[\n\r\]" $text] {
  68.         regsub -all "\[\n\r\]" $text "\r[text::indentTo $pos]" text
  69.     }
  70.     if [regexp "…" $text] {
  71.         regsub -all "…" $text [text::halfTab] text
  72.     }
  73.     setMark
  74.     if [regsub -all {•[^•]*•} $text "•" text] {
  75.         insertText $text
  76.         goto $pos
  77.         if $center { centerRedraw }
  78.         # need to go to the first tab stop
  79.         ring::+
  80.     } else {
  81.         insertText $text
  82.         if $center { centerRedraw }
  83.         return
  84.     }
  85. }
  86.  
  87.  
  88. # ◊◊◊◊ possible tab key bindings ◊◊◊◊ #
  89. # note: Also provided by the base Alpha system, these overide when 
  90. # Univs Completions package is in use (these may be more intricate).
  91.  
  92. ## 
  93.  # -------------------------------------------------------------------------
  94.  #     
  95.  #    "bind::IndentOrNextstop" --
  96.  #    
  97.  #     Either    insert a real tab if your mode hasn't defined its electricTab
  98.  #     variable, or jump to the next template    stop (if we're mid-template),
  99.  #     or    indent the current line    correctly.
  100.  #     
  101.  #     If this proc doesn't seem to do the right thing.  Make sure you've
  102.  #     got 'electricTab' set correctly in your preferences!
  103.  # -------------------------------------------------------------------------
  104.  ##
  105. proc bind::IndentOrNextstop {{hard 0}} {
  106.     if {$hard || ![elec::_haveTab] } {
  107.         insertActualTab 
  108.     } else {
  109.         if {![ring::+]} {bind::IndentLine}
  110.     }
  111. }
  112.  
  113. ## 
  114.  # -------------------------------------------------------------------------
  115.  #     
  116.  #    "bind::TabOrComplete" --
  117.  #    
  118.  #     Either    insert a real tab if your mode hasn't defined its electricTab
  119.  #     variable, or invoke the completion mechanism, or indent the current 
  120.  #     line correctly.
  121.  #     
  122.  #     If this proc doesn't seem to do the right thing.  Make sure you've
  123.  #     got 'electricTab' set correctly in your preferences!
  124.  # -------------------------------------------------------------------------
  125.  ##
  126. proc bind::TabOrComplete {{hard 0}} {
  127.     if {$hard || ![elec::_haveTab] } {
  128.         insertActualTab 
  129.     } else {
  130.         bind::Completion
  131.     }
  132. }
  133.  
  134. proc elec::_haveTab {} {
  135.     global electricTab
  136.     if [info exists electricTab] { return $electricTab } else { return 0 }
  137. }
  138.  
  139. proc ring::+ {} {
  140.     set pos [getPos]
  141.     if {[pos::compare $pos == [maxPos]]} { return 0 }
  142.     set searchResult [lindex [search -s -n -f 1 -m 0 -i 1 -r 0 {•} $pos] 0]
  143.     if {[string length $searchResult]} {
  144.         goto $searchResult
  145.         deleteChar
  146.         return 1
  147.     } else {
  148.         return 0
  149.     }
  150. }
  151.  
  152. proc ring::- {} {
  153.     set pos [getPos]
  154.     if {[pos::compare $pos == 0]} { return 0 }
  155.     set searchResult [lindex [search -s -n -f 0 -m 0 -i 1 -r 0 {•} $pos] 0]
  156.     if {[string length $searchResult]} {
  157.         goto $searchResult
  158.         deleteChar
  159.         return 1
  160.     } else {
  161.         return 0
  162.     }
  163. }
  164.  
  165. # Removes all tab stops from the current selection (if there is one) 
  166. # or the current document, maintaining the cursor position in the 
  167. # latter case.
  168. proc ring::clear {} {
  169.     watchCursor
  170.     set pos [getPos]
  171.     if {[pos::compare [set start $pos] == [set end [selEnd]]]} {
  172.         set start 0
  173.         set end [maxPos]
  174.         set text1 [getText $start $pos]
  175.         set subs1 [regsub -all {•} $text1 {} text1]
  176.         set text2 [getText $pos $end]
  177.         set subs2 [regsub -all {•} $text2 {} text2]
  178.         append text $text1 $text2
  179.         replaceText $start $end $text
  180.         goto [pos::math $pos - $subs1]
  181.         message "[expr $subs1 + $subs2] stops cleared"
  182.     } else {
  183.         set text [getText $start $end]
  184.         set subs3 [regsub -all {•} $text {} text]
  185.         replaceText $start $end $text
  186.         set end [getPos]
  187.         select $start $end
  188.         message "$subs3 stops cleared"
  189.     }
  190. }
  191. # indicates we're a very basic ring
  192. proc ring::type {} { return 0 }
  193. ## 
  194.  # -------------------------------------------------------------------------
  195.  # 
  196.  # "elec::CenterInsertion" --
  197.  # 
  198.  #  Insert and then do a refresh.  Useful for large electric insertions.
  199.  # -------------------------------------------------------------------------
  200.  ##
  201. proc elec::CenterInsertion {args} {
  202.     eval elec::_Insertion 1 $args
  203. }
  204.  
  205. ## 
  206.  # -------------------------------------------------------------------------
  207.  # 
  208.  # "elec::Insertion" --
  209.  # 
  210.  #  Just insert the electric item
  211.  # -------------------------------------------------------------------------
  212.  ##
  213. proc elec::Insertion { args } {
  214.     eval elec::_Insertion 0 $args
  215. }
  216. proc elec::ReplaceText { start end args } {
  217.     deleteText $start $end 
  218.     eval elec::_Insertion 0 $args
  219. }
  220.  
  221. ## 
  222.  # -------------------------------------------------------------------------
  223.  #     
  224.  #    "elec::Wrap" --
  225.  #    
  226.  #     Currently doesn't deal    with indentation --    the    wrapper    is supposed
  227.  #     to    handle that.
  228.  #     
  229.  #     Returns 0/1 to indicate if there was a selection which this proc
  230.  #     wrapped.
  231.  # -------------------------------------------------------------------------
  232.  ##
  233. proc elec::Wrap { left right {complete 0}} {
  234.     set pos [getPos]
  235.     set s [getSelect]
  236.     deleteText $pos [selEnd]
  237.     elec::Insertion $left $s $right
  238.     if {$s == ""} {
  239.         if $complete {
  240.             bind::Completion
  241.         }
  242.         return 0
  243.     }
  244.     return 1
  245. }
  246.  
  247. namespace eval pos {}
  248.  
  249. # These simple procs can be over-ridden by more advanced template
  250. # or completion code.
  251. proc pos::compare {p1 op p2} {return [expr $p1 $op $p2]}
  252. proc pos::math {p1 op p2} {return [expr $p1 $op $p2]}
  253.  
  254.